package com.foftact.block;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.foftact.block.mapper.BlockMapper;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 板块数据服务实现类
 */
@Service("blockService")
public class BlockServiceImpl implements BlockService {

    private static final Logger logger = LoggerFactory.getLogger(BlockServiceImpl.class);
    private static final String DATA_SOURCE = "block_api";
    private static final String API_URL = "https://push2.eastmoney.com/api/qt/clist/get?np=1&fltt=1&invt=2&cb=jQuery37105035489658017578_1760721847631&fs=m%3A90%2Bt%3A2%2Bf%3A!50&fields=f12%2Cf13%2Cf14%2Cf1%2Cf2%2Cf4%2Cf3%2Cf152%2Cf20%2Cf8%2Cf104%2Cf105%2Cf128%2Cf140%2Cf141%2Cf207%2Cf208%2Cf209%2Cf136%2Cf222&fid=f3&pn=$$pn$$&pz=$$pz$$&po=1&dect=1&ut=fa5fd1943c7b386f172d6893dbfba10b&wbp2u=%7C0%7C0%7C0%7Cweb&_=1760721847651";
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private BlockMapper blockMapper;

    @Override
    @Transactional
    public int fetchAndSaveBlockData() {
        logger.info("开始抓取板块数据，时间：{}", sdf.format(new Date()));
        int result = 0;
        int page = 0;
        int pageSize = 20;

        do {
            try {
                page ++;
                // 1. 抓取数据
                String jsonData = fetchDataFromApi(page, pageSize);
                // 2. 解析数据
                List<Block> blocks = parseBlockData(jsonData);
                if (blocks.size() <= 0) {
                    break;
                }
                // 3. 批量保存数据
                result += batchSaveBlock(blocks);

                logger.info("板块数据抓取保存成功，数量：{}", result);
            } catch (Exception e) {
                logger.error("抓取板块数据失败", e);
                throw new RuntimeException("抓取板块数据失败", e);
            }
        } while (true);

        // 4. 删除超过1年的旧数据
        deleteOldData(365);
        return result;
    }

    private String fetchDataFromApi(int pn, int pz) throws Exception {
        try {
            String url = StringUtils.replace(API_URL, "$$pn$$", String.valueOf(pn));
            url = StringUtils.replace(url, "$$pz$$", String.valueOf(pz));
            logger.info("开始抓取板块数据，pn : {} url : {}", pn, url);
            // 使用Jsoup发送GET请求
            Connection jsoupConn = Jsoup.connect(API_URL).timeout(10000);
            jsoupConn.referrer("https://quote.eastmoney.com/center/gridlist.html#industry_board");
            jsoupConn.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");

            org.jsoup.Connection.Request request = jsoupConn.request();
            request.ignoreContentType(true);
            request.url(new URL(url));
            Connection.Response response = jsoupConn.execute();
            int responseCode = response.statusCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                String jsonResponse = response.body();
                // 处理JSONP回调函数包装
                int start = jsonResponse.indexOf("(") + 1;
                int end = jsonResponse.lastIndexOf(")");
                if (start > 0 && end > start) {
                    jsonResponse = jsonResponse.substring(start, end);
                }
                return jsonResponse;
            } else {
                // 模拟数据，实际项目中应该抛出异常
                return StringUtils.EMPTY;
            }
        } catch (Exception e) {
            // 返回模拟数据以便测试
            return StringUtils.EMPTY;
        }
    }

    private List<Block> parseBlockData(String jsonData) throws Exception {
        List<Block> blocks = new ArrayList<>();
        JSONObject jsonObject = JSON.parseObject(jsonData, JSONReader.Feature.AllowUnQuotedFieldNames);
        JSONArray dataArray = jsonObject.getJSONArray("data.diff");

        if (dataArray != null) {
            for (int i = 0; i < dataArray.size(); i++) {
                JSONObject node = dataArray.getJSONObject(i);
                Block block = convertToBlock(node);
                if (block != null) {
                    blocks.add(block);
                }
            }
        }
        return blocks;
    }

    private Block convertToBlock(JSONObject node) {
        Block block = new Block();
        block.setCode(node.getString("f12"));
        block.setName(node.getString("f14"));
        block.setMarketCode("CN");
        block.setVolume(0L);
        block.setAmount(node.getLongValue("f20"));
        block.setChangePercent(new BigDecimal(node.getString("f8")).multiply(new BigDecimal(100*100)));
        block.setDataSource(DATA_SOURCE);
        block.setValid(true);
        return block;
    }

    @Override
    @Transactional
    public int saveBlock(Block block) {
        try {
            int result = blockMapper.insertOrUpdate(block);
            logger.info("保存单个板块数据成功：{}", block.getCode());
            return result;
        } catch (Exception e) {
            logger.error("保存单个板块数据失败：{}", block.getCode(), e);
            throw new RuntimeException("保存板块数据失败", e);
        }
    }

    @Override
    @Transactional
    public int batchSaveBlock(List<Block> blocks) {
        try {
            // 对数据进行过滤，只保存有效的数据
            List<Block> validBlocks = filterDataToSave(blocks);
            if (validBlocks.isEmpty()) {
                return 0;
            }
            
            int result = blockMapper.batchInsert(validBlocks);
            logger.info("批量保存板块数据成功，数量：{}", validBlocks.size());
            return result;
        } catch (Exception e) {
            logger.error("批量保存板块数据失败", e);
            throw new RuntimeException("批量保存板块数据失败", e);
        }
    }

    private List<Block> filterDataToSave(List<Block> blocks) {
        List<Block> validBlocks = new ArrayList<>();
        for (Block block : blocks) {
            // 简单的数据过滤逻辑，确保关键字段不为空
            if (block.getCode() != null && !block.getCode().isEmpty() &&
                block.getName() != null && !block.getName().isEmpty()) {
                validBlocks.add(block);
            }
        }
        return validBlocks;
    }

    @Override
    public Block getBlockByCode(String code) {
        try {
            return blockMapper.selectByCode(code);
        } catch (Exception e) {
            logger.error("根据代码获取板块数据失败：{}", code, e);
            throw new RuntimeException("获取板块数据失败", e);
        }
    }

    @Override
    public List<Block> getAllBlocks() {
        try {
            return blockMapper.selectAll();
        } catch (Exception e) {
            logger.error("获取所有板块数据失败", e);
            throw new RuntimeException("获取所有板块数据失败", e);
        }
    }

    @Override
    @Transactional
    public int deleteOldData(int days) {
        try {
            int result = blockMapper.deleteOldData(days);
            logger.info("删除{}天前的旧数据，数量：{}", days, result);
            return result;
        } catch (Exception e) {
            logger.error("删除旧数据失败", e);
            throw new RuntimeException("删除旧数据失败", e);
        }
    }
}